package com.zmzncs.lmtc.common.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Maps;
import com.zmzncs.lmtc.common.pojo.bolian.BolianCurrOrderRes;
import com.zmzncs.lmtc.common.pojo.bolian.BolianOrderHistoryRes;
import com.zmzncs.lmtc.common.pojo.bolian.BolianPrePayRes;
import com.zmzncs.lmtc.common.pojo.bolian.BolianQueryParkByIdRes;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Component
public class BolianUtil {

    //  泊链分配的车主厂商编号
    public static String userUnionId;
    @Value("${bolian.userUnionId}")
    public void setUserUnionId(String userUnionId) {
        this.userUnionId = userUnionId;
    }

    //  泊链分配的车主密钥
    public static String userKey;
    @Value("${bolian.userKey}")
    public void setUserKey(String userKey) {
        this.userKey = userKey;
    }

    //  泊链分配的停车场厂商编号
    public static String parkUnionId;
    @Value("${bolian.parkUnionId}")
    public void setParkUnionId(String parkUnionId) {
        this.parkUnionId = parkUnionId;
    }

    //  泊链分配的停车场密钥
    public static String parkKey;
    @Value("${bolian.parkKey}")
    public void setParkKey(String parkKey) {
        this.parkKey = parkKey;
    }

    //  上传车主信息
    public static String addUserUrl;
    @Value("${bolian.request-url.addUser}")
    public void setAddUser(String addUser) {
        addUserUrl = addUser;
    }

    //  更新车主信息车主
    public static String updateUserUrl;
    @Value("${bolian.request-url.updateUser}")
    public void setUpdateUser(String updateUser) {
        updateUserUrl = updateUser;
    }

    //  查询实时订单
    public static String queryCurrOrder;
    @Value("${bolian.request-url.queryCurrOrder}")
    public void setQueryCurrOrder(String queryCurrOrder) {
        this.queryCurrOrder = queryCurrOrder;
    }

    //  查询历史订单
    public static String queryOrders;
    @Value("${bolian.request-url.queryOrders}")
    public void setQueryOrders(String queryOrders) {
        this.queryOrders = queryOrders;
    }

    //  查询停车场
    public static String queryParks;
    @Value("${bolian.request-url.queryParks}")
    public void setQueryParks(String queryParks) {
        this.queryParks = queryParks;
    }

    //提交停车进场纪录
    public static String inPark;
    @Value("${bolian.request-url.inPark}")
    public void setInPark(String inPark) {
        this.inPark = inPark;
    }

    //提交停车出场记录
    public static String outPark;
    @Value("${bolian.request-url.outPark}")
    public void setOutPark(String outPark) {
        this.outPark = outPark;
    }

    //  根据泊链车场编号查询停车场信息
    public static String queryParkById;
    @Value("${bolian.request-url.queryParkById}")
    public static void setQueryParkById(String queryParkById) {
        BolianUtil.queryParkById = queryParkById;
    }

    //  预支付地址
    public static String prePay;
    @Value("${bolian.request-url.prePay}")
    public void setPrePay(String prePay) {
        this.prePay = prePay;
    }

    //  预支付地址
    public static String payMonthCard;
    @Value("${bolian.request-url.payMonthCard}")
    public void setPayMonthCard(String payMonthCard) {
        this.payMonthCard = payMonthCard;
    }

    //  查询车主在场订单
    public static String queryCarOrder;
    @Value("${bolian.request-url.queryCarOrder}")
    public void setQueryCarOrder(String queryCarOrder) {
        this.queryCarOrder = queryCarOrder;
    }

    //  上传停车场信息
    public static String addPark;
    @Value("${bolian.request-url.addPark}")
    public void setAddPark(String addPark) {
        this.addPark = addPark;
    }

    //  修改停车场信息
    public static String updatePark;
    @Value("${bolian.request-url.updatePark}")
    public void setUpdatePark(String updatePark) {
        this.updatePark = updatePark;
    }


    public static  final String SERVICE_SUBSIDY = "service_subsidy"; // 接口手续费回退补贴
    public static  final String PARK_OUT_PAY = "out_park_pay"; // 车主出场缴费
    public static  final String SERVICE_FEE = "service_fee"; // 三方接口服务收费

    public static void main(String[] args) {

    }

    /**
     * 交易流水号
      */
    public static String  getTradeNo() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        Date date = new Date();
        String str = simpleDateFormat.format(date);
        Random random = new Random();
        int rannum = (int) (random.nextDouble() *5);// 获取5位随机数
        return str + rannum;// 当前时间 + 系统5随机生成位数
    }

    /**
     * sign签名
     */
    public static String createSign(Map<String, Object> packageParams, String key) {
        StringBuffer sb = new StringBuffer();
        String dateStr = JSON.toJSONString(packageParams);
        sb.append(dateStr);
        sb.append("key=" + key);
        String sign = MD5Util.md5ToUpperCase(sb.toString());
        return sign;
    }

    /**
     * 预支付
     */
    public static BolianPrePayRes prePay(String orderCode, String tradeNo, String carNumber, String parkUnionId, String parkId, String payableAmount, Long customerId){
        Map<String, Object> params = Maps.newHashMap();
        params.put("union_id", BolianUtil.userUnionId );    //  厂商编号
        params.put("order_id", orderCode);    //  交易单号,与进场通知传过来的订单编号一致
        params.put("plate_number", carNumber);    //  车牌号码
        params.put("park_union_id", parkUnionId);  //  车场所属厂商编号
        params.put("park_id", parkId); //  车场编号
        params.put("prepay", payableAmount); //  应收金额
        params.put("pay_time", System.currentTimeMillis()/1000);   //  支付时间
        params.put("user_id", customerId);   //  车主编号
        params.put("trade_no", tradeNo);    //  交易流水号
        params.put("pay_channel", 0);   // 0微信 1支付宝 3银联 4建行
//        params.put("attach", attach);   // 附加属性,原装返回支付平台调用6.1预付订单通知传来的attach参数
        params.put("rand", Math.random());  //  随机数

        String jsonParams = BolianUtil.getRequestParams(params, userKey);
        log.info("泊链预支付请求参数：{}", jsonParams);

        String payResultStr = HttpUtil.getIntance().postJson(prePay, jsonParams);
        log.info("泊链预支付响应数据：{}", payResultStr);
        BolianPrePayRes bolianPrePayRes = null;
        try {
            bolianPrePayRes = JSONObject.parseObject(payResultStr, BolianPrePayRes.class);
            if(!bolianPrePayRes.getState().equals(1)){
                log.error(bolianPrePayRes.getErrmsg());
            }
        } catch (Exception e) {
            log.error("泊链预支付响应数据解析出错");
        }

        return bolianPrePayRes;
    }

    /**
     * 根据泊链车场编号查询停车场信息
     */
    public static BolianQueryParkByIdRes queryParkById(String com_id){
        Map<String, Object> params = new HashMap();
        params.put("union_id", userUnionId);    //  厂商编号
        params.put("com_id", com_id);   //   结束时间
        params.put("rand", Math.random());  //  随机数

        String jsonParams = BolianUtil.getRequestParams(params, userKey);
        log.info("根据泊链车场编号查询停车场请求参数：{}", jsonParams);

        String payResultStr = HttpUtil.getIntance().postJson(queryOrders, jsonParams);
        BolianQueryParkByIdRes bolianQueryParkByIdRes = JSONObject.parseObject(payResultStr, BolianQueryParkByIdRes.class);
        log.info("根据泊链车场编号查询停车场响应数据：{}", bolianQueryParkByIdRes);

        return bolianQueryParkByIdRes;
    }

    /**
     * 查询历史订单
     */
    public static BolianOrderHistoryRes queryOrders(String orderCode, String parkUnionId, String parkId, String carNum, Long startTime, Long endTime, Integer page, Integer size){
        Map<String, Object> params = new HashMap();
//        Long startTime = DateTimeUtil.getStartOfDay(DateTimeUtil.getDaysAgoDate(daysAgo)).getTime()/1000;
//        Long endTime = DateTimeUtil.getEndOfDay(new Date()).getTime()/1000;
        params.put("union_id", userUnionId);    //  厂商编号
        params.put("park_union_id", parkUnionId);    //  停车场厂商编号，接口文档没有，专供
        params.put("park_id", parkId);    //  车场编号，接口文档没有，专供
        params.put("plate_number", carNum);    //  车牌号
        params.put("order_id", orderCode);    //  订单编号
        params.put("start_time", startTime);    //  开始时间
        params.put("end_time", endTime);   //   结束时间
        params.put("page", page);   //   查询页码
        params.put("size", size);   //   每次返回查询记录数
        params.put("rand", Math.random());  //  随机数

        String jsonParams = BolianUtil.getRequestParams(params, userKey);
        log.info("泊链历史订单请求参数：{}", jsonParams);

        String payResultStr = HttpUtil.getIntance().postJson(queryOrders, jsonParams);
        log.info("泊链历史订单响应数据：{}", payResultStr);

        BolianOrderHistoryRes bolianOrderHistoryRes = JSONObject.parseObject(payResultStr, BolianOrderHistoryRes.class);
        //  plate_number字段不生效，所以如果carNum不为空，则去除其他车牌数据
        if(bolianOrderHistoryRes.getData() != null && StringUtils.isNotBlank(carNum)){
            Iterator<BolianOrderHistoryRes.OrderHistoryData> iterator = bolianOrderHistoryRes.getData().iterator();
            while (iterator.hasNext()){
                BolianOrderHistoryRes.OrderHistoryData historyData = iterator.next();
                if (!historyData.getCar_number().equals(carNum)){
                    log.info("泊链历史订单-查询车牌【{}】，结果出现车牌【{}】，所有去除车牌【{}】的数据", carNum, historyData.getCar_number(), historyData.getCar_number());
                    iterator.remove();
                }
            }
        }

        //  计算总金额
        BigDecimal totalMoney = new BigDecimal(0);
        if(bolianOrderHistoryRes.getData() != null) {
            for (BolianOrderHistoryRes.OrderHistoryData orderHistoryData: bolianOrderHistoryRes.getData()) {
                totalMoney = totalMoney.add(new BigDecimal(orderHistoryData.getMoney()));
            }
        }
        bolianOrderHistoryRes.setTotalMoney(totalMoney);   //  订单总金额
        log.info("泊链历史订单总金额：{}", bolianOrderHistoryRes.getTotalMoney());

        return bolianOrderHistoryRes;
    }

    /**
     *  查询实时订单
     */
    public static BolianCurrOrderRes quercurrorder(String orderCode, String carNumber, String parkUnionId, String parkId){
        long startTime = new Date().getTime();

        Map<String, Object> params = new HashMap();
        params.put("union_id", BolianUtil.userUnionId );
        params.put("order_id", orderCode);  //  有本平台车主在其它平台车场的停车入场订单时必传
        params.put("plate_number", carNumber);
        params.put("park_union_id", parkUnionId);
        params.put("park_id", parkId);
        params.put("rand", Math.random());
        String jsonParams = BolianUtil.getRequestParams(params, userKey);
        log.info("泊链实时订单请求参数：{}", jsonParams);
        String resultStr = HttpUtil.getIntance().postJson(queryCurrOrder, jsonParams);
        log.info("泊链实时订单响应数据：{}，耗时{}ms", resultStr, new Date().getTime()-startTime);
        BolianCurrOrderRes bolianCurrOrderRes = JSONObject.parseObject(resultStr, BolianCurrOrderRes.class);

        return bolianCurrOrderRes;
    }

    /**
     * 将请求参数转换为json格式的string
     */
    public static String getRequestParams(Map<String, Object> map, String key) {
        JSONObject jsonObject = new JSONObject();
        String sign = BolianUtil.createSign(map, key);
        jsonObject.put("data", map);
        jsonObject.put("sign", sign);
        return jsonObject.toString();
    }

    /**
     * 验证签名
     */
    public static boolean isTenpaySign(String data, String sign) {
        StringBuffer sb = new StringBuffer();
        sb.append(data);
        sb.append("key=" + userKey);
        String tenpaySign = MD5Util.md5ToUpperCase(sb.toString());
        return tenpaySign.equals(sign);
    }

    /**
     *  校验泊链接口响应是否成功
     */
    public static boolean resultIsSuccess(String resultStr) {
        if(StringUtils.isNotBlank(resultStr)){
            JsonNode jsonNode = JsonUtil.getJsonNode(resultStr);
            String state = jsonNode.get("state").toString();
            if(state.equals("1")){
                return true;
            }
        }
        return false;
    }

    /**
     * 上传会员信息到泊链
     */
    public static Boolean addUserToBoLian(Long custocmerId, String carNum) {
        Map<String, Object> paramsa = Maps.newHashMap();
        paramsa.put("union_id", userUnionId);
        paramsa.put("user_id", custocmerId);
        paramsa.put("plate_number", carNum);
        paramsa.put("nosence_pay", "1");
        paramsa.put("rand", Math.random());

        String jsonParams = BolianUtil.getRequestParams(paramsa, userKey);
        log.info("泊链上传会员请求参数：{}", jsonParams);
        String resultStr = HttpUtil.getIntance().postJson(addUserUrl, jsonParams);
        log.info("泊链上传会员响应数据：" + resultStr);

        Boolean isSuccess = BolianUtil.resultIsSuccess(resultStr);

        return isSuccess;
    }


    /**
     * 从泊链删除会员信息
     */
    public static Boolean deleteUserFromBoLian(Long custocmerId, String carNum) {
        Map<String, Object> paramsa = Maps.newHashMap();
        paramsa.put("union_id", userUnionId);
        paramsa.put("type", 2);   //删除会员
        paramsa.put("user_id", custocmerId);
        paramsa.put("plate_number", carNum);
        paramsa.put("nosence_pay", 1);
        paramsa.put("rand", Math.random());
        String jsonParams =  getRequestParams(paramsa, userKey);
        log.info("泊链删除会员请求参数：" + jsonParams);
        String resultStr = HttpUtil.getIntance().postJson(updateUserUrl,jsonParams);
        log.info("泊链删除会员响应数据：" + resultStr);

        Boolean isSuccess = resultIsSuccess(resultStr);

        return isSuccess;
    }

    /**
     *  添加客户新车牌到泊链
     */
    public static Boolean addUserCarNumberToBoLian(Long custocmerId, String carNum) {
        Map<String, Object> paramsa = Maps.newHashMap();
        paramsa.put("union_id", userUnionId);
        paramsa.put("type", 3);   //3更新或添加新车牌
        paramsa.put("user_id", custocmerId);
        paramsa.put("plate_number",carNum);
        paramsa.put("nosence_pay", "1");
        paramsa.put("rand", Math.random());
        String jsonParams =  getRequestParams(paramsa, userKey);
        log.info("泊链添加车牌请求参数：" + jsonParams);
        String resultStr = HttpUtil.getIntance().postJson(updateUserUrl, jsonParams);
        log.info("泊链添加车牌响应数据：" + resultStr);

        Boolean isSuccess = resultIsSuccess(resultStr);

        return isSuccess;
    }

    /**
     *  修改客户在泊链存储的车牌
     */
    public static Boolean updateUserCarNumberToBoLian(Long custocmerId, String carNum, String newCarNum) {
        Map<String, Object> paramsa = Maps.newHashMap();
        paramsa.put("union_id", userUnionId);
        paramsa.put("type", 3);   //3更新或添加新车牌
        paramsa.put("user_id", custocmerId);
        paramsa.put("plate_number",carNum);
        paramsa.put("new_plate_number", newCarNum); //  type=3传值时,修改上面的车牌，为空时，新加上面的车牌
        paramsa.put("nosence_pay", "1"); //  是否开通无感	0否，1是
        paramsa.put("rand", Math.random());
        String jsonParams =  getRequestParams(paramsa, userKey);
        log.info("泊链修改车牌请求参数：" + jsonParams);
        String resultStr = HttpUtil.getIntance().postJson(updateUserUrl, jsonParams);
        log.info("泊链修改车牌响应数据：" + resultStr);

        Boolean isSuccess = resultIsSuccess(resultStr);

        return isSuccess;
    }

    /**
     *  删除客户车牌从泊链
     */
    public static Boolean deleteUserCarNumberFromBoLian(Long custocmerId, String carNum) {
        Map<String, Object> paramsa = Maps.newHashMap();
        paramsa.put("union_id", userUnionId);
        paramsa.put("type", 4);   //4删除车牌
        paramsa.put("user_id", custocmerId);
        paramsa.put("plate_number",carNum);
        paramsa.put("nosence_pay", "1");
        paramsa.put("rand", Math.random());
        String jsonParams =  getRequestParams(paramsa, userKey);
        log.info("泊链删除车牌请求参数：" + jsonParams);
        String resultStr = HttpUtil.getIntance().postJson(updateUserUrl, jsonParams);
        log.info("泊链删除车牌响应数据：" + resultStr);

        Boolean isSuccess = resultIsSuccess(resultStr);

        return isSuccess;
    }


    /**
     *提交停车进场纪录
     */
    public static Boolean addInParkOrder(String parkId,String carNumber,Long inTime,String orderId,Integer emptyPlot){
        Map<String, Object> paramsa = Maps.newHashMap();
        paramsa.put("union_id", parkUnionId); //厂商编号
        paramsa.put("park_id", parkId); //车场编号
        paramsa.put("car_number", carNumber); //车牌
        paramsa.put("in_time",inTime); //进场时间(unix时间戳格式，精确到秒)
        paramsa.put("order_id", orderId); //订单记录号
        paramsa.put("empty_plot", emptyPlot); //空闲车位数
        String jsonParams =  getRequestParams(paramsa, parkKey);
        log.info("泊链提交进场纪录参数：" + jsonParams);
        String resultStr = HttpUtil.getIntance().postJson(inPark, jsonParams);
        log.info("泊链提交进场纪录响应数据：" + resultStr);

        Boolean isSuccess = resultIsSuccess(resultStr);
        if(isSuccess == false){
            log.error("{}", JSONObject.parseObject(resultStr).getString("errmsg"));
        }

        return isSuccess;
    }

    /**
     *提交停车出场记录
     */
    public static String addOutParkOrder(String parkId,String carNumber,Long inTime,Long outTime, String orderId,Integer emptyPlot, String total){
        Map<String, Object> params = Maps.newHashMap();
        params.put("union_id", parkUnionId); //厂商编号
        params.put("park_id", parkId); //车场编号
        params.put("car_number", carNumber); //车牌
        params.put("in_time",inTime); //进场时间(unix时间戳格式，精确到秒)
        params.put("out_time", outTime); //出场时间(unix时间戳格式，精确到秒)
        params.put("pay_type", "cash"); //支付类型：cash:现金，wallet:余额支付，sweepcode:扫码枪支付
        params.put("empty_plot", emptyPlot); //空闲车位数
        params.put("total", total); //	订单金额
        params.put("order_id", orderId); //订单记录号
        String jsonParams =  getRequestParams(params, parkKey);
        log.info("泊链提交出场记录请求参数：" + jsonParams);
        String resultStr = HttpUtil.getIntance().postJson(outPark, jsonParams);
        log.info("泊链提交出场记录响应数据：" + resultStr);

        Boolean isSuccess = resultIsSuccess(resultStr);
        if(isSuccess == false){
            log.error("{}", JSONObject.parseObject(resultStr).getString("resultStr"));
        }

        return resultStr;
    }


    /**
     *  查询车主在场订单
     */
    public static String queryCarOrder(String carNumber) {
        Map<String, Object> params = Maps.newHashMap();
        params.put("union_id", userUnionId); // 厂商编号
        params.put("plate_number", carNumber); //   车牌
        params.put("rand", Math.random());  //  随机数
        String jsonParams =  getRequestParams(params, userKey);
        log.info("泊链查询车主在场订单请求参数：" + jsonParams);
        String resultStr = HttpUtil.getIntance().postJson(queryCarOrder, jsonParams);
        log.info("泊链查询车主在场订单响应数据：" + resultStr);

        return resultStr;
    }

    /**
     *  添加新停车场到泊链
     */

    public static String addNewParkToBoLian(String parkId, String name,String address,String phone,String lng,String lat,
                                            Integer totalPlot, Integer emptyPlot,String priceDesc) {
        Map<String, Object> paramsa = Maps.newHashMap();
        paramsa.put("park_id", parkId);//厂商平台的车场编号，不可重复
        paramsa.put("name", name);   //车场名称
        paramsa.put("address", address);//地址
        paramsa.put("city_id",130100);//城市编码(默认石家庄市)
        paramsa.put("phone", phone);//联系手机号
        paramsa.put("lng", lng);//经度
        paramsa.put("lat", lat);//纬度
        paramsa.put("total_plot", totalPlot);//总车位数
        paramsa.put("empty_plot", emptyPlot);//空闲车位数
        paramsa.put("union_id", parkUnionId);//厂商编号
        paramsa.put("price_desc", priceDesc);//价格描述
        paramsa.put("rand", Math.random());//随机数

        String jsonParams =  getRequestParams(paramsa, parkKey);
        log.info("泊链添加停车场请求参数：" + jsonParams);
        String resultStr = HttpUtil.getIntance().postJson(addPark, jsonParams);
        log.info("泊链添加停车场响应结果：" + resultStr);

        return resultStr;
    }


    /**
     *  更新停车场信息到泊链
     */
    public static String updateParkToBoLian(String parkId, Integer type,Integer totalPlot, Integer emptyPlot,String priceDesc) {
        Map<String, Object> paramsa = Maps.newHashMap();
        paramsa.put("park_id", parkId);//厂商平台的车场编号，不可重复
        paramsa.put("type", type);   //1上传余位数/修改价格，2禁用车场
        paramsa.put("union_id", parkUnionId);//厂商编号
        paramsa.put("total_plot", totalPlot);//总车位数
        paramsa.put("empty_plot", emptyPlot);//空闲车位数
        paramsa.put("price_desc", priceDesc);//价格描述
        paramsa.put("rand", Math.random());//随机数

        String jsonParams =  getRequestParams(paramsa, parkKey);
        String resultStr = HttpUtil.getIntance().postJson(updatePark, jsonParams);

        log.info("更新停车场信息到泊链");
        log.info("请求泊链地址：" + updatePark);
        log.info("请求泊链参数：" + jsonParams);
        log.info("请求泊链响应结果：" + resultStr);

        return resultStr;
    }

}
